package com.guozhi.demo.dev;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class DefaultManageResourceClass implements ManageResourceClass {

    // 从配置文件中获取类路径
    private GetClassName getClassName;

    // 加载指定类到虚拟机
    private LoadClass loadClass;

    // 存放已加载过的resource中类文件的实例, 线程安全
    private Map<String, Object> resourceClasses = new ConcurrentHashMap<>();

    // 单例模式
    private DefaultManageResourceClass(String propertiesPath) throws IOException {
        getClassName = new GetClassName(propertiesPath);
        loadClass = new LoadClass();
    }

    private static DefaultManageResourceClass instance;

    public static DefaultManageResourceClass getInstance(String propertiesPath) throws IOException {
        if (instance == null)
            synchronized (DefaultManageResourceClass.class) {
                if (instance == null)
                    instance = new DefaultManageResourceClass(propertiesPath);
            }
        return instance;
    }

    public static DefaultManageResourceClass getInstance() {
        if (instance == null)
            throw new RuntimeException("未配置类加载的配置文件");
        return instance;
    }

    /**
     * 根据配置文件获取指定类的实例
     *
     * @param javaName
     * @return
     */
    @Override
    public Object getObject(String javaName) throws InterruptedException, IOException, ClassNotFoundException, InstantiationException, IllegalAccessException {
        Object o = resourceClasses.get(javaName);
        if (o == null)
            o = loadObject(javaName);
        return o;
    }

    /**
     * 从resource文件中重新加载指定类文件
     *
     * @param javaName
     * @return
     */
    @Override
    public Object reloadObject(String javaName) throws InterruptedException, ClassNotFoundException, InstantiationException, IllegalAccessException, IOException {
        resourceClasses.remove(javaName);
        return loadObject(javaName);
    }

    /**
     * 将指定java类加载到 resourceClass容器中
     * @param javaName 配置文件中的文件名
     * @return 实例化的对象
     */
    private Object loadObject(String javaName) throws InterruptedException, IOException, ClassNotFoundException, IllegalAccessException, InstantiationException {
        String javaPath = getClassName.getClassName(javaName);
        Class c = loadClass.load(javaPath);
        Object o = c.newInstance();
        resourceClasses.put(javaName, o);
        return o;
    }


}
